5.2. 구조체를 사용한 예제 프로그램

넓이 구하기 프로그램

넓이를 구하는 프로그램을 구현할 때는 가로, 세로 값이 필요할 것이다.
이 값을 묶지 않아도 되지만, 안정성을 위해서는 묶어주는 것이 좋다.
튜플로 묶게 될 경우 개발자는 가로, 세로라는 순서를 지켜야 하며 그 의미를 파악하는 것도 어렵다.

struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!(
        "The area of the rectangle is {} square pixels.",
        area(&rect1)
    );
}

fn area(rectangle: &Rectangle) -> u32 {
    rectangle.width * rectangle.height
}

이렇게 해주면 값의 의미가 명확하다.
순서도 지켜야 할 필요 없다.
소유권을 가져가버리면 이후 사용할 수 없기 때문에 참조자를 활용했다.

트레이트 파생으로 유용한 기능 추가하기

구조체를 출력해보고 싶다면 어떻게 해야 하는가?
Pasted image 20240501133730.png
단순하게 println!을 사용하면 이러한 에러가 나온다.
:?를 추가하면 디버그 출력형식을 사용하는 방법이다.
Pasted image 20240501133803.png
에러 메시지를 보고 수정하면 이러한 에러가 뜬다.
우리가 만든 구조체에 디버그 기능을 넣으려면 구현을 시켜주어야만 한다.

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
}

외부 속성을 구조체 정의 직전에 작성하여 이를 해결한다.
Pasted image 20240501134205.png
원래는 한 줄로 출력되지만 :#?로 바꿔주면 이렇게 줄이 바뀐다.

dbg! 매크로

Debug 포맷으로 출력하려면 dbg! 매크로를 사용하는 방법도 있다.
이것은 표현식의 소유권을 가져와 출력한 후 다시 소유권을 반환한다.
dbg!는 stderr에 출력을 진행한다.
println은 stdout에 출력한다.

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let scale = 2;
    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };

    dbg!(&rect1);
}

Pasted image 20240501134652.png
이렇게 두서 없이 사방에 dbg를 뿌리면, 해당 값의 결과를 알 수 있다.
몇번째 줄인지, 원래 값은 무엇인지도 알려준다.
참고로 구조체에 Debug 포맷을 넣어줬기에 가능한 것이다.

러스트에서는 Debug 트레이트 말고도 derive 속성으로 다양한 동작을 추가시켜줄 수 있다.